home *** CD-ROM | disk | FTP | other *** search
/ Die Speccy' 97 / Die Speccy' 97.iso / amiga_system / the_aminet / comm / bbs / s342q07.lha / log.c < prev    next >
C/C++ Source or Header  |  1994-11-13  |  23KB  |  858 lines

  1. /*
  2. *       log.c
  3. *
  4. * userlog code for Citadel bulletin board system.
  5. */
  6. /*
  7. *       history
  8. *
  9. * 85Nov15 HAW  MS-DOS library implemented.
  10. * 85Aug31 HAW  Fix <.ep> problem.
  11. * 85Aug17 HAW  Update to onLine().
  12. * 85Aug10 HAW  Fix so system doesn't go out to disk on short pwds.
  13. * 85Jul26 HAW  Kill noteLog(), insert anti-hack code in newPW().
  14. * 85Jun13 HAW  Tweak code for networking stuff.
  15. * 85Mar13 HAW  Moved zapLogFile() and logInit and logSort into confg.c.
  16. * 85Jan19 HAW  Fix terminate() so room prompt isn't tossed at modem.
  17. * 85Jan19 HAW  New Users are now directed to type ".help POLICY".
  18. * 85Jan19 HAW  Move findPerson() into file.
  19. * 84Dec15 HAW  Fix bug that allowed discovery of private rooms.
  20. * 84Aug30 HAW  Now we roll into the 16-bit world.
  21. * 84Jun23 HAW&JLS  Eliminating unused local variables using CRF.
  22. * 84Jun19 JLS  Fixed terminate so that Mail> doesn't screw up SYSOP.
  23. * 84Apr04 HAW  Started upgrade to BDS C 1.50a.
  24. * 83Feb27 CrT  Fixed login-in-Mail> bug.
  25. * 83Feb26 CrT  Limited # new messages for new users.
  26. * 83Feb18 CrT  Null pw problem fixed.
  27. * 82Dec06 CrT  2.00 release.
  28. * 82Nov03 CrT  Began local history file & general V1.2 cleanup
  29. */
  30. #include "ctdl.h"
  31. /*
  32. *       contents
  33. *
  34. *      doInviteDisplay()       displays invited users
  35. *      GetUser()    gets a user record from user
  36. *      login()      is menu-level routine to log caller in
  37. *      newPW()      is menu-level routine to change a PW
  38. *      newUser()    menu-level routine to log a new caller
  39. *      PWSlot()   returns CTDLLOG.buf slot password is in
  40. *      slideLTab()    support routine for sorting logTab
  41. *      storeLog()   store data in log
  42. *      strCmpU()    strcmp(), but ignoring case distinctions
  43. *      terminate()    menu-level routine to exit system
  44. */
  45. int   thisSlot;   /* logTab slot logBuf found via */
  46. char    loggedIn = FALSE;      /* Global have-caller flag      */
  47. char    prevChar;   /* for EOLN/EOParagraph stuff   */
  48. static char      pwChangeCount;   /* Anti-hack variable   */
  49. int   logTries;
  50. extern logBuffer logBuf;    /* Log buffer of a person       */
  51. extern logBuffer logTmp;    /* Log buffer of a person       */
  52. extern LogTable *logTab;    /* RAM index of pippuls   */
  53. LogTable *delogTab = NULL;    /* RAM index of pippuls   */
  54. extern CONFIG cfg;    /* Configuration variables      */
  55. extern rTable *roomTab;   /* RAM index of rooms   */
  56. extern aRoom  roomBuf;    /* Room buffer    */
  57. extern MessageBuffer   tempMess, msgBuf;
  58. extern char   heldMess;
  59. extern FILE   *logfl;   /* log file descriptor    */
  60. extern int    thisLog;    /* entry currently in logBuf    */
  61. extern char   outFlag;    /* Output skip flag   */
  62. extern char   whichIO;    /* Where IO's going...    */
  63. extern char   haveCarrier;       /* Do we still got carrier?     */
  64. extern char   echo;   /* Who gets what    */
  65. extern char   onConsole;    /* Where we get stuff from      */
  66. extern int    thisRoom;   /* The room we're in    */
  67. extern int    exitValue;
  68. extern char      DiskHeld;
  69.  
  70. static int Bad_String(char *string, char *filename);
  71.  
  72.  
  73. /*
  74. * doInviteDisplay()
  75. *
  76. * This function shows invited users.
  77. */
  78. char doInviteDisplay()
  79.   {
  80.   int rover = 0, s;
  81.   label who;
  82.   if (getNormStr("", who, NAMESIZE, BS_VALID) == BACKED_OUT)
  83.   return BACKED_OUT;
  84.   if (strLen(who) == 0)
  85.     {
  86.     mPrintf("%s, ", logBuf.lbname);
  87.     outFlag = OUTOK;
  88.     for (; outFlag == OUTOK && rover < cfg.MAXLOGTAB; rover++)
  89.       {
  90.       if (rover != thisLog)
  91.         {
  92.         getLog(&logTmp, rover);
  93.         if (logTmp.lbflags.L_INUSE &&
  94.         (s = knowRoom(&logTmp, thisRoom)) == KNOW_ROOM ||
  95.         s == WRITE_PRIVS)
  96.           {
  97.           mPrintf("%s", logTmp.lbname);
  98.           if (s == WRITE_PRIVS && roomBuf.rbflags.READ_ONLY)
  99.           mPrintf(" (w-p)");
  100.           mPrintf(", ");
  101.  
  102.           }
  103.  
  104.         }
  105.  
  106.       }
  107.     mPrintf("\b\b.");
  108.  
  109.     }
  110.   else
  111.     {
  112.     if (findPerson(who, &logTmp) == ERROR)
  113.     mPrintf("Who?\n ");
  114.     else if ((s = knowRoom(&logTmp, thisRoom)) == KNOW_ROOM ||
  115.     s == WRITE_PRIVS)
  116.     mPrintf("Affirmative!\n ");
  117.     else
  118.     mPrintf("Negative!\n ");
  119.  
  120.     }
  121.   return GOOD_SELECT;
  122.  
  123.   }
  124. /*
  125. * GetUser()
  126. *
  127. * This is a general function for requesting user name, getting user record,
  128. * and doing error checking.  Returns ERROR on failure.
  129. */
  130. int GetUser(label who, logBuffer *lBuf, char Menu)
  131.   {
  132.   int logNo;
  133.   if (Menu && onConsole)
  134.   SysopRequestString(NO_MENU, "WHOUSR", who, NAMESIZE, 0);
  135.   else getNormStr("WHOUSR", who, NAMESIZE, 0);
  136.   if (strLen(who)             == 0 )          return ERROR;
  137.   if (strCmpU(who, "Citadel") == SAMESTRING ) return (int)cfg.MAXLOGTAB;
  138.   if (strCmpU(who, "Sysop") == SAMESTRING)  strCpy(who, cfg.SysopName);
  139.   logNo = findPerson(who, lBuf);
  140.   if (logNo == ERROR)
  141.     {
  142.     if (Menu && onConsole)
  143.     SysopError(NO_MENU, "No such person...\n ");
  144.     else mPrintf("No such person...\n ");
  145.  
  146.     }
  147.   return logNo;
  148.  
  149.   }
  150. /*
  151. * DoAllQuestion()
  152. *
  153. * This will ask if someone wants to apply an operation to all users.
  154. */
  155. int DoAllQuestion(char *posprompt, char *negprompt)
  156.   {
  157.   if (SysopGetYesNo(NO_MENU, NULL, posprompt)) return TRUE;
  158.   if (SysopGetYesNo(NO_MENU, NULL, negprompt)) return FALSE;
  159.   return ERROR;
  160.  
  161.   }
  162. /*
  163. * login()
  164. *
  165. * This is the menu-level routine to log someone in.
  166. */
  167. void login(char *password)
  168.   {
  169.   int  foundIt;
  170.   int  Adoor;
  171.   extern char *READ_ANY, *LCHeld, shownHidden;
  172.   extern long *DL_Total;
  173.   extern SListBase DL_List;
  174.   TwoNumbers *tmp;
  175.   foundIt =    ((PWSlot(password, /*load = */TRUE)) != ERROR);
  176.   pwChangeCount = 1;
  177.   if (foundIt && *password)
  178.     {
  179.     /* update userlog entries: */
  180.     heldMess     = FALSE;
  181.     loggedIn     = TRUE;
  182.     setUp(TRUE);
  183.     /* recite caller's name, etc:    */
  184.     Output_Citadel_Message("WELCOM",NULL, NULL, NULL);
  185.     Update_Caller_Count();              /* update the stats */
  186.     Output_Citadel_Message("CCPRIV",NULL, NULL, NULL);
  187.     Adoor = CheckAutoDoor("Citadel");
  188.     (void)RunAutoDoor(Adoor, FALSE);
  189.     (void)RunAutoDoor(CheckAutoDoor(logBuf.lbname), FALSE);
  190.     ScrNewUser();
  191.     HelpIfPresent("Notice.PRE");
  192.     if (!MultiBanner("Notice")) HelpIfPresent("Notice.BLB");
  193.     HelpIfPresent("Notice.SFX");
  194.     logMessage(L_IN, logBuf.lbname, FALSE);
  195.     showMessages(NEWoNLY, FALSE,
  196.     logBuf.lbvisit[logBuf.lbgen[thisRoom] & CALLMASK],
  197.     OptionValidate);
  198.     listRooms(expert ? INT_EXPERT : INT_NOVICE);
  199.     if (shownHidden )
  200.       Output_Citadel_Message("HIDDEN",NULL,NULL,NULL);
  201.     /*
  202.     * This code sets up to handle download time limits.  Users who
  203.     * download are kept in a list -- user# + time spent in downloading.
  204.     * The list is cleared whenever the system is brought down/up, or
  205.     * a d-l time limit #event expires or initiates.  Here, we check to
  206.     * see if this user has downloaded during the current period.  If so,
  207.     * we simply point at the record so we know how much time has already
  208.     * been spent downloading.  If not found, we initialize a new record.
  209.     */
  210.     if ((DL_Total = SearchList(&DL_List, (tmp = MakeTwo(thisLog, 0l))))
  211.     == NULL)
  212.       {
  213.       DL_Total = &tmp->second;
  214.       AddData(&DL_List, tmp, NULL, TRUE);
  215.  
  216.       }
  217.     else free(tmp);
  218.     outFlag = OUTOK;
  219.     if (
  220.     (
  221.     logBuf.lbMail[MAILSLOTS-1].rbmsgNo >
  222.     (logBuf.lbvisit[   logBuf.lbgen[MAILROOM] & CALLMASK   ])
  223.     )
  224.     &&
  225.     (logBuf.lbMail[MAILSLOTS-1].rbmsgNo & S_MSG_MASK) > cfg.oldest
  226.     &&
  227.     thisRoom != MAILROOM
  228.     )
  229.       {
  230.       Output_Citadel_Message("YRMAIL",NULL, NULL, NULL);
  231.       }
  232.     if (GetIntMessage())
  233.       {
  234.       outFlag = OUTOK;
  235.       DiskHeld = TRUE;
  236.       Output_Citadel_Message("HAVHLD",NULL, NULL, NULL);
  237.  
  238.       }
  239.  
  240.     }
  241.   else
  242.     {
  243.     /* discourage password-guessing: */
  244.     if (cfg.LoginAttempts > 0 && logTries++ >= cfg.LoginAttempts)
  245.     if (whichIO == MODEM)
  246.       {
  247.       Output_Citadel_Message("HACKLG", NULL, NULL, NULL);
  248.       HangUp(TRUE);
  249.       return ;  /* skip the pause() farther on */
  250.  
  251.       }
  252.     if (strLen(password) > 1 && whichIO == MODEM)
  253.     if ((logTries-1) > 2 ) pause(2000);
  254.     if (!cfg.BoolFlags.unlogLoginOk  &&  whichIO == MODEM)
  255.       {
  256.       if (!HelpIfPresent("UnLog.BLB"))
  257.       Output_Citadel_Message("NOACCT",NULL, NULL, NULL);
  258.  
  259.       }
  260.     else
  261.       {
  262.       if (getYesNo("NORCRE"))
  263.         {
  264.         SpecialMessage("Status:Creating New Account");
  265.         newUser(&logBuf);
  266.         Update_Caller_Count();              /* update the stats */
  267.         }
  268.  
  269.       }
  270.  
  271.     }
  272.  
  273.   }
  274. /*
  275. * GetIntMessage()
  276. *
  277. * This will get an interrupted message from the Held dir.
  278. */
  279. char GetIntMessage()
  280.   {
  281.   extern FILE *upfd;
  282.   SYS_FILE funFile;
  283.   label temp;
  284.   /* if the user used Pause-E, we don't want to flush the buffer */
  285.   if (!heldMess)
  286.   ZeroMsgBuffer(&tempMess);
  287.   if (cfg.BoolFlags.HoldOnLost)
  288.     {
  289.     sPrintf(temp, LCHeld, thisLog);
  290.     makeSysName(funFile, temp, &cfg.holdArea);
  291.     if ((upfd = safeopen(funFile, READ_ANY)) != NULL)
  292.       {
  293.       fread(&tempMess, STATIC_MSG_SIZE, 1, upfd);
  294.       crypte(&tempMess, STATIC_MSG_SIZE, thisLog);
  295.       fread(tempMess.mbtext, MAXTEXT, 1, upfd);
  296.       crypte(tempMess.mbtext, MAXTEXT, thisLog);
  297.       MakeList(&tempMess.mbCC, "", upfd);
  298.       fclose(upfd);
  299.       unlink(funFile);
  300.       heldMess = TRUE;
  301.       return TRUE;
  302.  
  303.       }
  304.  
  305.     }
  306.   return FALSE;
  307.  
  308.   }
  309. /*
  310. * newPW()
  311. *
  312. * This is menu-level routine to change one's password.  Since some Citadel
  313. * nodes run in public locations, we avoid displaying passwords on the console.
  314. */
  315. void newPW()
  316.   {
  317.   char oldPw[NAMESIZE];
  318.   char pw[NAMESIZE];
  319.   int  goodPW;
  320.   extern char *confirm;
  321.   if (!loggedIn)
  322.     {
  323.     mPrintf("\n How?\n ");
  324.     return ;
  325.  
  326.     }
  327.   /* save password so we can find current user again: */
  328.   strcpy(oldPw, logBuf.lbpw);
  329.   storeLog();
  330.   do
  331.     {
  332.     echo    = CALLER;
  333.     getNormStr("UPASSW", pw, NAMESIZE, NO_ECHO);
  334.     echo    = BOTH;
  335.     if (strLen(pw) == 0 || strCmpU(pw, oldPw) == SAMESTRING)
  336.       {
  337.       PWSlot(oldPw, /*load = */TRUE);
  338.       return ;
  339.  
  340.       }
  341.     /* check that PW isn't already claimed: */
  342.     goodPW = (PWSlot(pw,/* load = */TRUE) == ERROR  &&  strLen(pw) >= 5);
  343.     if( goodPW && strcmp(logBuf.lbpw,pw)==0)goodPW = FALSE;
  344.     if( goodPW && Bad_String(pw, "badpasswords.sys") )goodPW = FALSE;
  345.     if (pwChangeCount == 0 && !onConsole && onLine())
  346.       {
  347.       Output_Citadel_Message("HANGON",NULL, NULL, NULL);
  348.       pause(3000);      /* Discourage hacking       */
  349.       }
  350.     else pwChangeCount--;
  351.     if (!goodPW)
  352.       Output_Citadel_Message("POORCH",NULL, NULL, NULL);
  353.     }
  354.   while (!goodPW && (haveCarrier || whichIO==CONSOLE));
  355.   doCR();
  356.   PWSlot(oldPw, /*load = */TRUE);     /* reload old log entry */
  357.   pw[NAMESIZE-1] = 0x00;    /* insure against loss of carrier:*/
  358.   if (goodPW  &&  strLen(pw) > 1)
  359.     {
  360.     /* accept new PW:   */
  361.     mPrintf("\n %s\n Password: ", logBuf.lbname);
  362.     echo = CALLER;
  363.     mPrintf("%s\n ", pw);
  364.     echo = BOTH;
  365.     if (getYesNo("CONFRM"))
  366.       {
  367.       strcpy(logBuf.lbpw, pw);
  368.       logTab[0].ltpwhash      = hash(pw);
  369.       storeLog();
  370.  
  371.       }
  372.  
  373.     }
  374.  
  375.   }
  376. /*
  377. * newUser()
  378. *
  379. * This is the add new user function.
  380. */
  381. void newUser(logBuffer *lBuf)
  382.   {
  383.   logBuffer   l2;
  384.   char  *temp;
  385.   char  fullnm[NAMESIZE], tmp[30];
  386.   SYS_FILE    checkHeld;
  387.   char  pw[NAMESIZE], NewLogin;
  388.   int   g, h, i, ourSlot, AttemptCount = 0;
  389.   int   good; /* does double duty, keep it as int */
  390.   MSG_NUMBER  low;
  391.   TwoNumbers *ttemp;
  392.   extern char *LCHeld/* , IsAutoMail*/;
  393.   if (!NewUserDoor())
  394.     {
  395.     HangUp(TRUE);
  396.     return;
  397.  
  398.     }
  399.   NewLogin = (lBuf == &logBuf) ;
  400.   if (NewLogin)
  401.   HelpIfPresent("NewUser.BLB");
  402.   zero_struct(lBuf->lbflags);     /* zero all flags */
  403.   lBuf->lbflags.LFMASK = TRUE;    /* except we need linefeeds */
  404.   if (!configure(lBuf, !NewLogin, TRUE))  /* configure correctly */
  405.   return;
  406.   initLogBuf(&l2);
  407.   Output_Citadel_Message("PASSWD",NULL,NULL,NULL);
  408.   do
  409.     {
  410.     /* get name and check for uniqueness... */
  411.     if (AttemptCount++ > cfg.LoginAttempts)
  412.       Output_Citadel_Message("MINDPW", NULL, NULL, NULL);
  413.     if (AttemptCount > cfg.LoginAttempts + 2 && NewLogin)
  414.     if (whichIO == MODEM) HangUp(TRUE);
  415.     do
  416.       {
  417.       getNormStr("USRNAM", fullnm, NAMESIZE, 0);
  418.       if ((temp = strchr(fullnm, '@')) != NULL)*temp='\0'; /* fix for bad user names */
  419.       NormStr(fullnm);
  420.       good = TRUE;
  421.       if( findPerson(fullnm, &l2) != ERROR) good = FALSE;
  422.       if( Bad_String(fullnm, "badnames.sys" ) ) good = FALSE;
  423.       h = hash(fullnm);
  424.       if (    h == 0    /* "HUH?" --HAW 84Aug31   */  )
  425.         {
  426.         good = FALSE;
  427.  
  428.         }
  429.       /* lie sometimes -- hash collision !=> name collision */
  430.       if (!good)
  431.         {
  432.         if (strLen(fullnm) == 0)
  433.           {
  434.           if (getYesNo("ABORTA"))
  435.             {
  436.             killLogBuf(&l2);
  437.             setUp(NewLogin);
  438.             logTries++;
  439.             return ;
  440.  
  441.             }
  442.  
  443.           }
  444.         else Output_Citadel_Message("NOTNEW", (long)fullnm, NULL, NULL);
  445.         }
  446.  
  447.       }
  448.     while (!good  &&  (haveCarrier || whichIO==CONSOLE));
  449.     /* get password and check for uniqueness...     */
  450.     do
  451.       {
  452.       echo  = CALLER;
  453.       getNormStr("UPASSW",  pw, NAMESIZE, 0);
  454.       good = TRUE;
  455.       echo  = BOTH  ;
  456.       if( strlen(pw) < 5)
  457.         {
  458.         good = FALSE;
  459.         Output_Citadel_Message("2SHORT",NULL,NULL,NULL);
  460.         };
  461.       if( good &&  strCmpU(fullnm,pw) == 0 ) good = FALSE;
  462.       if( good &&  Bad_String(pw, "badpasswords.sys" ) ) good = FALSE;
  463.       h    = hash(pw);
  464.       for (i = 0; i < cfg.MAXLOGTAB && good; i++)
  465.         {
  466.         if (h == logTab[i].ltpwhash) good = FALSE;
  467.  
  468.         }
  469.       if (h == 0)   good = FALSE;
  470.       if (!good)
  471.         {
  472.         if (strLen(pw) == 0)
  473.           {
  474.           if (getYesNo("ABORTA"))
  475.             {
  476.             killLogBuf(&l2);
  477.             setUp(NewLogin);
  478.             logTries++;
  479.             return ;
  480.  
  481.             }
  482.  
  483.           }
  484.         else Output_Citadel_Message("POORCH", NULL, NULL, NULL);
  485.         }
  486.  
  487.       }
  488.     while( !good  &&  (haveCarrier || whichIO==CONSOLE));
  489.     mPrintf("\n Username: %s", fullnm);
  490.     mPrintf("\n Password: ");
  491.     echo = CALLER;
  492.     mPrintf("%s\n ", pw);
  493.     echo = BOTH;
  494.  
  495.     }
  496.   while (!getYesNo("OKPROM") && (haveCarrier || whichIO==CONSOLE));
  497.   if ((haveCarrier || whichIO == CONSOLE))
  498.     {
  499.     if (NewLogin)
  500.     logMessage(L_IN, fullnm, '+');
  501.     /* kick least recent temporary acct out of userlog and claim entry: */
  502.     for (good = cfg.MAXLOGTAB-1; good >= 0; good--)
  503.     if (!logTab[good].ltpermanent) break;
  504.     if (good < 0) good = cfg.MAXLOGTAB - 1; /* too bad */
  505.     ourSlot   = logTab[good].ltlogSlot;
  506.     slideLTab((NewLogin) ? 0 : 1, good);
  507.     logTab[NewLogin ? 0 : 1].ltlogSlot = ourSlot;
  508.     if (NewLogin)
  509.     thisLog = ourSlot;
  510.     /* copy info into record:       */
  511.     strcpy(lBuf->lbname, fullnm);
  512.     strcpy(lBuf->lbpw, pw);
  513.     lBuf->lbflags.L_INUSE    = TRUE;
  514.     lBuf->lbflags.NET_PRIVS  = cfg.BoolFlags.NetDft;
  515.     lBuf->lbflags.DOOR_PRIVS = cfg.BoolFlags.DoorDft;
  516.     lBuf->lbflags.DL_PRIVS   = cfg.BoolFlags.DL_Default;
  517.     lBuf->credit             = 0;  /* No L-D credit  */
  518.     low                      = cfg.newest-50;
  519.     if (cfg.oldest - low < 0x8000)   low = cfg.oldest;
  520.     for (i=1;  i<MAXVISIT;  i++)   lBuf->lbvisit[i]= low;
  521.     lBuf->lbvisit[0]         = cfg.newest;
  522.     lBuf->lbvisit[(MAXVISIT-1)] = cfg.oldest;
  523.     /* initialize rest of record:   */
  524.     for (i = 0;  i < MAXROOMS;  i++)
  525.       {
  526.       if (roomTab[i].rtflags.PUBLIC == 1)
  527.         {
  528.         g = (roomTab[i].rtgen);
  529.         lBuf->lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  530.  
  531.         }
  532.       else
  533.         {
  534.         /* set to one less */
  535.         g = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
  536.         lBuf->lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
  537.  
  538.         }
  539.  
  540.       }
  541.     memset(lBuf->lbMail, 0, MAIL_BULK);
  542.     /* fill in logTab entries       */
  543.     i = (NewLogin) ? 0 : 1;
  544.     logTab[i].ltpwhash      = hash(pw)  ;
  545.     logTab[i].ltnmhash      = hash(fullnm)    ;
  546.     logTab[i].ltlogSlot     = ourSlot ;
  547.     logTab[i].ltnewest      = lBuf->lbvisit[0];
  548.     logTab[i].ltpermanent   = FALSE;  /* new accts not perm */
  549.     /* special kludge for Mail> room, to signal no new mail:   */
  550.     if (NewLogin)
  551.       {
  552.       loggedIn = TRUE;
  553.       roomTab[MAILROOM].rtlastMessage =
  554.       lBuf->lbMail[MAILSLOTS-1].rbmsgNo;
  555.  
  556.       }
  557.     /* automatic mail for the new user. */
  558.     makeSysName(checkHeld, (lBuf->lbflags.EXPERT) ? "ExpMail.BLB" :
  559.     "NovMail.BLB", &cfg.homeArea);
  560.     if (access(checkHeld, 0) == 0)
  561.       {
  562.       i = thisRoom;
  563.       getRoom(MAILROOM);
  564.       ZeroMsgBuffer(&msgBuf);
  565.       ingestFile(checkHeld, &msgBuf);
  566.       strCpy(msgBuf.mbauth, (strLen(cfg.SysopName)) ?
  567.       cfg.SysopName : "Citadel");
  568.       strCpy(msgBuf.mbto, lBuf->lbname);
  569.       putMessage(lBuf);
  570.       /* IsAutoMail = FALSE; */
  571.       getRoom(i);
  572.  
  573.       }
  574.     ClearBio(ourSlot);
  575.     if (NewLogin)
  576.       {
  577.       storeLog();
  578.       ScrNewUser();
  579.       if (expert)
  580.         {
  581.         if (getYesNo("WRTBIO"))
  582.         EditBio();
  583.  
  584.         }
  585.       /*
  586.       * Create a new download record.  See login() for more details.
  587.       */
  588.       AddData(&DL_List, ttemp = MakeTwo(thisLog, 0l), NULL, TRUE);
  589.       DL_Total = &ttemp->second;
  590.  
  591.       }
  592.     if (cfg.BoolFlags.HoldOnLost)
  593.       {
  594.       sPrintf(tmp, LCHeld, ourSlot);
  595.       makeSysName(checkHeld, tmp, &cfg.holdArea);
  596.       unlink(checkHeld);
  597.  
  598.       }
  599.     if (NewLogin)
  600.       {
  601.       if (!MultiBanner("Notice"))
  602.       HelpIfPresent("Notice.BLB");
  603.       listRooms(expert ? INT_EXPERT : INT_NOVICE);
  604.       Output_Citadel_Message("RDHELP",NULL, NULL, NULL);
  605.       }
  606.     else
  607.       {
  608.       logTab[1].ltnewest    = cfg.newest;
  609.       lBuf->lbvisit[0]      = cfg.newest;
  610.       lBuf->lbflags.DOOR_PRIVS = getYesNo("DRPRIV");
  611.       lBuf->lbflags.DL_PRIVS  = getYesNo("DLPRIV");
  612.       lBuf->lbflags.AIDE      = getYesNo("ADPRIV");
  613.       if (cfg.BoolFlags.netParticipant)
  614.       lBuf->lbflags.NET_PRIVS = getYesNo("NTPRIV");
  615.       if( lBuf->lbflags.NET_PRIVS)
  616.         lBuf->credit          = SysopGetNumber(NULL, "HWMYCR", 0l, 1000l);
  617.       putLog(lBuf, ourSlot);
  618.  
  619.       }
  620.  
  621.     }
  622.   killLogBuf(&l2);
  623.  
  624.   }
  625. /*
  626. * PWSlot()
  627. *
  628. * This returns ctdllog.sys slot password is in, else ERROR.
  629. * NB: we also leave the record for the user in logBuf.
  630. */
  631. int PWSlot(char pw[NAMESIZE], char load)
  632.   {
  633.   int  h, i;
  634.   int  foundIt, ourSlot;
  635.   if (strLen(pw) < 2)   /* Don't search for these pwds    */
  636.   return ERROR;
  637.   h = hash(pw);
  638.   /* Check all passwords in memory: */
  639.   for(i = 0, foundIt = FALSE;  !foundIt && i < cfg.MAXLOGTAB;  i++)
  640.     {
  641.     /* check for password match here */
  642.     /* If password matches, check full password */
  643.     /* with current newUser code, password hash collisions should   */
  644.     /* not be possible... but this is upward compatable & cheap     */
  645.     if (logTab[i].ltpwhash == h)
  646.       {
  647.       ourSlot     = logTab[i].ltlogSlot;
  648.       getLog(&logTmp, ourSlot);
  649.       if (strCmpU(pw, logTmp.lbpw) == SAMESTRING)
  650.         {
  651.         /* found a complete match */
  652.         thisSlot = i   ;
  653.         foundIt  = TRUE;
  654.  
  655.         }
  656.  
  657.       }
  658.  
  659.     }
  660.   if (foundIt)
  661.     {
  662.     if (load == TRUE)
  663.       {
  664.       copyLogBuf(&logTmp, &logBuf);
  665.       thisLog = ourSlot;
  666.  
  667.       }
  668.     return thisSlot;
  669.  
  670.     }
  671.   return ERROR   ;
  672.  
  673.   }
  674. /*
  675. * slideLTab()
  676. *
  677. * This slides bottom N lots in logTab down.  For sorting.
  678. */
  679. void slideLTab(int slot, int last)
  680.   {
  681.   int i;
  682.   /* open slot up: (movmem isn't guaranteed on overlaps) */
  683.   for (i = last - 1;  i >= slot;  i--)
  684.     {
  685.     memcpy(&logTab[i + 1], logTab + i, cfg.sizeLTentry);
  686.  
  687.     }
  688.  
  689.   }
  690. /*
  691. * storeLog()
  692. *
  693. * This function stores the current log record.
  694. */
  695. void storeLog()
  696.   {
  697.   logTab[0].ltnewest    = cfg.newest;
  698.   logBuf.lbvisit[0]     = cfg.newest;
  699.   putLog(&logBuf, thisLog);
  700.  
  701.   }
  702. /*
  703. * strCmpU()
  704. *
  705. * This is strcmp(), but ignoring case distinctions.  Really, it's stricmp().
  706. */
  707. #define MXBF 60
  708. int strCmpU(char s[], char t[])
  709.   {
  710.   int  i,j;
  711.   if ( (j=strlen(s)) > 50 || (i=strlen(t)) > 50 )
  712.     {
  713.     int k;
  714.     char buff[MXBF+1];
  715.     if( j > MXBF)
  716.       {
  717.       splitF(NULL,"*** Warning: String  1 longer than %d characters, truncated.\n",MXBF);
  718.       j = MXBF;
  719.  
  720.       };
  721.     for(k=0;k<j;k++) buff[k] = ( s[k] < ' ' || s[k] > '~') ? '.' : s[k];
  722.     buff[k] = '\0';
  723.     splitF(NULL, " s:%s\n",s);
  724.     if( i > MXBF)
  725.       {
  726.       splitF(NULL,"*** Warning: String 2 longer than %D characters, truncated.\n",MXBF);
  727.       j = MXBF;
  728.  
  729.       };
  730.     for(k=0;k<j;k++) buff[k] = ( t[k] < ' ' || t[k] > '~') ? '.' : t[k];
  731.     buff[k] = '\0';
  732.     splitF(NULL, " t:%s\n",buff);
  733.  
  734.     };
  735.   i = 0;
  736.   while (toUpper(s[i]) == toUpper(t[i]))
  737.     {
  738.     if (s[i] == '\0' || t[i] == '\0')  return 0;
  739.     i++;
  740.  
  741.     }
  742.   return  toUpper(s[i]) - toUpper(t[i]);
  743.  
  744.   }
  745. /*
  746. * terminate()
  747. *
  748. * This is the menu-level routine for a user to exit system.
  749. */
  750. void terminate(int discon, int save)
  751.   {
  752.   extern char heldMess, *READ_TEXT;
  753.   extern MessageBuffer  tempMess;
  754.   extern int  exitValue;
  755.   extern char ExitToMsdos, hst;
  756.   int i;
  757.   char  StillThere;
  758.   outFlag    = IMPERVIOUS;
  759.   DiskHeld   = FALSE;
  760.   StillThere = onLine();
  761.   /* this stops the .TS cheat of password hacking */
  762.   if (!loggedIn) discon = TRUE;
  763.   if (loggedIn && exitValue != DOOR_EXIT)
  764.       Output_Citadel_Message("GOODBY",NULL, NULL, NULL);
  765.   if (StillThere && exitValue != DOOR_EXIT)
  766.     {
  767.     HelpIfPresent("LoNotice.Pre");
  768.     if (!MultiBanner("LoNotice"))
  769.     HelpIfPresent("LoNotice.BLB");
  770.     HelpIfPresent("LoNotice.SFX");
  771.  
  772.     }
  773.   if (discon && exitValue != DOOR_EXIT)
  774.     {
  775.     switch (whichIO)
  776.       {
  777.       case MODEM:
  778.       if (onLine() && !cfg.BoolFlags.IsDoor)
  779.         {
  780.         pause(50);
  781.         HangUp(FALSE);
  782.         modIn();    /* And now detect carrier loss  */
  783.         while (MIReady()) inp();    /* clear buffer */
  784.  
  785.         }
  786.       break;
  787.       case CONSOLE:
  788.       whichIO =  MODEM;
  789.       EnableModem(FALSE);
  790.       if (!ExitToMsdos)
  791.         {
  792.         ReInitModem();
  793.         printf("\n System returned to MODEM MODE...\n ");
  794.  
  795.         }
  796.       startTimer(NEXT_ANYNET);    /* start up anytime net timer */
  797.       break;
  798.  
  799.       }
  800.     /* if we're functioning as a door ... */
  801.     if (cfg.BoolFlags.IsDoor)
  802.       {
  803.       ExitToMsdos = TRUE;
  804.       exitValue   = SYSOP_EXIT;   /* Seems appropriate */
  805.  
  806.       }
  807.  
  808.     }
  809.   Output_Citadel_Message("CHNGDT",NULL,NULL,NULL);
  810.   if (loggedIn)
  811.     {
  812.     ReadDate(formDate(), &logBuf.lblaston);
  813.     if (StillThere)
  814.     SetKnown(-1, 0, thisRoom, &logBuf);
  815.     if (save)       storeLog();
  816.     logBuf.lbname[0] = 0; /* For screen display */
  817.     if (heldMess)
  818.     SaveInterrupted(&tempMess);
  819.  
  820.     }
  821.   if (exitValue != DOOR_EXIT)
  822.   logMessage(L_OUT, "", (discon) ? 0 : '-');
  823.   loggedIn = FALSE;
  824.   setUp(TRUE);
  825.   for (i = 0; i < MAXROOMS; i++)      /* Clear skip bits */
  826.   roomTab[i].rtflags.SKIP = 0;
  827.   /*if (discon) CacheMessages(ALL_NETS, TRUE);*/
  828.   outFlag = OUTOK;
  829.   ScrNewUser();
  830.   if (exitValue != DOOR_EXIT)
  831.   getRoom(LOBBY);
  832.   ClearDoorTimers();
  833.   logBuf.lbflags.ANSI     = 0;
  834.   }
  835. /*
  836.  * Bad_String()
  837.  * This function will check to see if the requested file is available
  838.  * If it is not, it just returns FALSE and assumes the SYSOP does not
  839.  * have it or want it checked.
  840.  * This function searches the stringfile to discover if the requested
  841.  * string is acceptable or not.
  842.  */
  843. static int Bad_String(char *fullnm, char *stringfile)
  844. {
  845.     SYS_FILE name;
  846.     char line[25], toReturn = FALSE;
  847.     FILE *fd;
  848.     makeSysName(name, stringfile, &cfg.roomArea);
  849.     if ((fd = fopen(name, READ_TEXT)) != NULL)
  850.       {
  851.         while (GetAString(line, sizeof line, fd) != NULL && !toReturn)
  852.           if (strCmpU(fullnm, line) == 0) toReturn = TRUE;
  853.       fclose(fd);
  854.       };
  855.     return toReturn;
  856. }
  857.  
  858.